package com.his.server.exception;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.*;

public class MultiCauseException extends Exception
{

    private List causeList;
    
    public MultiCauseException()
    {
        causeList = new ArrayList();
    }

    public MultiCauseException(String message)
    {
        super(message);
        causeList = new ArrayList();
    }

    public MultiCauseException(Throwable cause)
    {
        super(cause == null ? null : cause.getMessage());
        causeList = new ArrayList();
        initCause(cause);
    }

    public MultiCauseException(String message, Throwable cause)
    {
        super(message);
        causeList = new ArrayList();
        initCause(cause);
    }

    public void addCause(Throwable cause)
    {
        causeList.add(cause);
    }

    public void addAllCause(List causeList)
    {
        this.causeList.addAll(causeList);
    }

    public Throwable initCause(Throwable cause)
    {
        if(causeList.size() != 0)
            throw new IllegalStateException("Can't overwrite cause");
        if(cause == this)
        {
            throw new IllegalArgumentException("Self-causation not permitted");
        } else
        {
            causeList.add(cause);
            return this;
        }
    }

    public void printStackTrace(PrintStream stream)
    {
        synchronized(stream)
        {
            super.printStackTrace(stream);
            if(causeList.size() == 1)
            {
                stream.print("Caused by: ");
                Throwable t = (Throwable)causeList.get(0);
                if(t != null)
                    t.printStackTrace(stream);
            } else
            if(causeList.size() > 1)
            {
                int count = 0;
                Iterator it = causeList.iterator();
                do
                {
                    if(!it.hasNext())
                        break;
                    Throwable t = (Throwable)it.next();
                    if(t != null)
                    {
                        stream.print("MultiCause[" + count++ + "]: Caused by: ");
                        t.printStackTrace(stream);
                    }
                } while(true);
            }
        }
    }

    public void printStackTrace(PrintWriter writer)
    {
        synchronized(writer)
        {
            super.printStackTrace(writer);
            if(causeList.size() == 1)
            {
                writer.write("Caused by: ");
                Throwable t = (Throwable)causeList.get(0);
                if(t != null)
                    t.printStackTrace(writer);
            } else
            if(causeList.size() > 1)
            {
                int count = 0;
                Iterator it = causeList.iterator();
                do
                {
                    if(!it.hasNext())
                        break;
                    Throwable t = (Throwable)it.next();
                    if(t != null)
                    {
                        writer.write("MultiCause[" + count++ + "]: Caused by: ");
                        t.printStackTrace(writer);
                    }
                } while(true);
            }
        }
    }

    public Throwable getCause()
    {
        Throwable cause = null;
        if(causeList.size() > 0)
            cause = (Throwable)causeList.get(0);
        return cause;
    }

    public Throwable[] getAllCauses()
    {
        return (Throwable[])(Throwable[])causeList.toArray(new Throwable[causeList.size()]);
    }

    public boolean isCauseMultiple()
    {
        return causeList.size() > 1;
    }

    public String toString()
    {
        StringBuffer buff = new StringBuffer(getClass().getName());
        if(causeList.size() > 1)
            buff.append(": Cause Count ").append(causeList.size());
        String message = getLocalizedMessage();
        if(message != null)
            buff.append(": ").append(message);
        return buff.toString();
    }

}